// strstream standard header -*-c++-*-
// Copyright 2009-2010 IAR Systems AB.
#ifndef _STRSTREAM_
#define _STRSTREAM_

#ifndef _SYSTEM_BUILD
#pragma system_include
#endif

#include <istream>
_STD_BEGIN

// CLASS strstreambuf
class strstreambuf
  : public streambuf
{       // stream buffer associated with static or allocated character array
public:
  enum
  {     // constants for bits in stream state
    _Allocated = 1,     // set if character array storage has been allocated
    _Constant = 2,      // set if character array nonmutable
    _Dynamic = 4,       // set if character array length grows on demand
    _Frozen = 8};       // set if character array ownership given away
  typedef int _Strstate;

  explicit strstreambuf(streamsize _Count = 0)
  {     // construct with empty character array, suggested initial size
    _Init(_Count);
  }

  strstreambuf(void *(*_Allocfunc)(size_t),
               void (*_Freefunc)(void *))
  {     // construct with empty character array, allocation functions
    _Init();
    _Palloc = _Allocfunc;
    _Pfree = _Freefunc;
  }

  strstreambuf(char *_Getptr, streamsize _Count, char *_Putptr = 0)
  {     // construct with [_Getptr, _Getptr + _Count), possibly mutable
    _Init(_Count, _Getptr, _Putptr);
  }

  strstreambuf(unsigned char *_Getptr, streamsize _Count,
               unsigned char *_Putptr = 0)
  {     // construct with [_Getptr, _Getptr + _Count), possibly mutable
    _Init(_Count, (char *)_Getptr, (char *)_Putptr);
  }

  strstreambuf(const char *_Getptr, streamsize _Count)
  {     // construct with [_Getptr, _Getptr + _Count), nonmutable
    _Init(_Count, (char *)_Getptr, 0, _Constant);
  }

  strstreambuf(const unsigned char *_Getptr, streamsize _Count)
  {     // construct with [_Getptr, _Getptr + _Count), nonmutable
    _Init(_Count, (char *)_Getptr, 0, _Constant);
  }

  virtual ~strstreambuf();      // destroy the object

  void freeze(bool = true);     // freeze or unfreeze writing

  char *str()
  {     // freeze and return pointer to character array
    freeze();
    return (gptr());
  }

  streamsize pcount() const
  {     // return size of writable character array
    return (pptr() == 0 ? 0 : (streamsize)(pptr() - pbase()));
  }

  strstreambuf(signed char *_Getptr, streamsize _Count,
               signed char *_Putptr = 0)
  {     // construct with [_Getptr, _Getptr + _Count), possibly mutable
    _Init(_Count, (char *)_Getptr, (char *)_Putptr);
  }

  strstreambuf(const signed char *_Getptr, streamsize _Count)
  {     // construct with [_Getptr, _Getptr + _Count), nonmutable
    _Init(_Count, (char *)_Getptr, 0, _Constant);
  }

protected:
  virtual int overflow(int = EOF);      // try to extend write area

  virtual int pbackfail(int = EOF);     // try to putback a character

  virtual int underflow();      // read if read position available

  virtual streampos seekoff(streamoff, // seek by specified offset
                            ios_base::seekdir,
                            ios_base::openmode = 
                            ios_base::in | ios_base::out); 

  virtual streampos seekpos(streampos, // seek to memorized position
                            ios_base::openmode =
                            ios_base::in | ios_base::out);      

  void _Init(streamsize = 0, char * = 0, char * = 0,
           _Strstate = (_Strstate)0); // initialize with possibly static buffer

  void _Tidy(); // free any allocated storage

private:
  enum
  {     // constant for default minimum buffer size
    _MINSIZE = 32};

  streamsize _Minsize;  // the minimum buffer size
  char *_Pendsave;      // the saved end pointer during freeze
  char *_Seekhigh;      // the high-water pointer in character array
  _Strstate _Strmode;   // the stream state
  void *(*_Palloc)(size_t);     // the pointer to allocator function
  void (*_Pfree)(void *);       // the pointer to free function
};

// CLASS istrstream
class istrstream
  : public istream
{       // input stream associated with a character array
public:

  explicit istrstream(const char *_Ptr)
    : istream(&_Mysb), _Mysb(_Ptr, 0)
  {     // construct with NTBS
  }

  istrstream(const char *_Ptr, streamsize _Count)
    : istream(&_Mysb), _Mysb(_Ptr, _Count)
  {     // construct with [_Ptr, _Ptr + _Count)
  }

  explicit istrstream(char *_Ptr)
    : istream(&_Mysb), _Mysb((const char *)_Ptr, 0)
  {     // construct with NTBS
  }

  istrstream(char *_Ptr, int _Count)
    : istream(&_Mysb), _Mysb((const char *)_Ptr, _Count)
  {     // construct with [_Ptr, _Ptr + _Count)
  }

  virtual ~istrstream();        // destroy the object

  strstreambuf *rdbuf() const
  {     // return pointer to character array buffer
    return ((strstreambuf *)&_Mysb);
  }

  char *str()
  {     // freeze and return pointer to character array
    return (_Mysb.str());
  }

private:
  strstreambuf _Mysb;   // the string buffer
};

// CLASS ostrstream
class ostrstream
  : public ostream
{       // output stream associated with a character array
public:
  ostrstream()
    : ostream(&_Mysb), _Mysb()
  {     // construct with empty character array
  }

  ostrstream(char *, streamsize,
             ios_base::openmode =
             ios_base::out);    // construct with static array

  virtual ~ostrstream();        // destroy the object

  strstreambuf *rdbuf() const
  {     // return pointer to character array buffer
    return ((strstreambuf *)&_Mysb);
  }

  void freeze(bool _Freezeit = true)
  {     // freeze or unfreeze writing
    _Mysb.freeze(_Freezeit);
  }

  char *str()
  {     // freeze and return pointer to character array
    return (_Mysb.str());
  }

  streamsize pcount() const
  {     // return size of writable character array
    return (_Mysb.pcount());
  }

private:
  strstreambuf _Mysb;   // the character array buffer
};
_STD_END
#endif /* _STRSTREAM_ */

/*
 * Copyright (c) 1992-2009 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 V5.04:0576 */
